#include "Scuba.h"
#include "Tokenizer.h"

#include "inGlobal.h"

#include<string>
#include<iostream>

using namespace std;

Scuba::Scuba(std::string sFileName)
{
    Scope *pxScope = new InGlobal(NULL);
    m_apxScope.push_back(pxScope);
    m_pxCurrentScope=pxScope;
	m_nLineNumber = 1;
	m_sFileName = sFileName;
	m_pxSymbolyzer = new Symbolyzer();
	m_pxSymbolyzer->setScope(*m_pxCurrentScope);

}

Scuba::~Scuba(void)
{
}

void Scuba::enterScope(Scope* inScope)
{
    Scope* pxOldScope = m_pxCurrentScope;

    m_apxScope.push_back(inScope);
    m_pxCurrentScope->m_asBody.push_back(""); //Please note that the position of a new scope is denoted by a '\0'
    m_pxCurrentScope = inScope;

	m_pxSymbolyzer->onScopeEntry(*m_pxCurrentScope, *pxOldScope);

    //Notify the observer
    if(NULL!=m_pxScubserver)
        m_pxScubserver->onScopeEntry(*m_pxCurrentScope, *pxOldScope);

}

void Scuba::exitScope(void)
{
    Scope* pxOldScope;

    pxOldScope = m_apxScope.back();
    m_apxScope.pop_back();
    m_pxCurrentScope = m_apxScope.back();

	m_pxSymbolyzer->onScopeExit (*m_pxCurrentScope, *pxOldScope);

    if(NULL!=m_pxScubserver)
        m_pxScubserver->onScopeExit(*m_pxCurrentScope, *pxOldScope);
}

void Scuba::feed(Token& inToken)
{
    bool bIsEndOfScope=false;
    Scope* pxScope = NULL;
	char cDelimiter = char(inToken);

    if('\n'==cDelimiter)
		m_nLineNumber++;

	m_pxSymbolyzer->onNewToken(*m_pxCurrentScope, inToken);

	if(NULL!=m_pxScubserver)
		m_pxScubserver->onNewToken(*m_pxCurrentScope, inToken);
	//TODO? It might be safer to inform Scubservers *AFTER* parse. Doubtful, but noting anyway

    pxScope = m_pxCurrentScope->parse(inToken, bIsEndOfScope);
    if(true==bIsEndOfScope)
        exitScope();
    
    if(NULL!=pxScope)
        enterScope(pxScope);

}

void Scuba::print()
{
    this->m_pxCurrentScope->printSymbols();
}

void Scuba::setObserver(Scubserver* inScubserver)
{
    m_pxScubserver = inScubserver;
	inScubserver->setScope(*m_pxCurrentScope);
}

void Scuba::setFileName(std::string sFileName)
{
	m_sFileName = sFileName;
}

